<?php

namespace App\Services\AetherUpload\Eloquent;

use App\Services\AetherUpload\Lib\LocalResource;
use App\Services\AetherUpload\Lib\OssResource;
use Illuminate\Support\Facades\Storage;

abstract class DriverResource
{
    public $config;
    public $storage;
    public $name;
    public $path;

    public function __construct($path, $disk)
    {
        $this->config = config('filesystems.disks.' . $disk);
        $this->storage = Storage::disk($disk);
        $this->path = trim($path, '/');
    }

    /**
     * @param $path
     * @param $disk
     * @return static
     * @throws \Exception
     */
    public static function getInstance($path, $disk): self
    {
        $driver = config('filesystems.disks.' . $disk . '.driver');
        switch ($driver) {
            case 'oss':
                return new OssResource($path, $disk);
            case 'local':
                return new LocalResource($path, $disk);
            default:
                throw new \Exception('not find filesystem disk');
        }
    }

    abstract public function append($path, $data, int $position = 0);

    abstract public function calculateHash();

    public function exists($path): bool
    {
        return $this->storage->exists($path);
    }

    public function put($path, $contents, $options = []): bool
    {
        return $this->storage->put($path, $contents, $options);
    }

    public function has($path): bool
    {
        return $this->storage->exists($path);
    }

    /**
     * Delete the file at a given path.
     *
     * @param string|array $paths
     * @return bool
     */
    public function delete($paths): bool
    {
        return $this->storage->delete($paths);
    }

    public function move($from, $to): bool
    {
        return $this->storage->move($from, $to);
    }

    public function makeDirectory($path): bool
    {
        return $this->storage->makeDirectory($path);
    }

    public function getPath(): string
    {
        return $this->path;
    }

    public function size(): int
    {
        return $this->storage->size($this->path);
    }

    public function mimeType()
    {
        return $this->storage->mimeType($this->path);
    }

    public function __call($name, $arguments)
    {
        if (method_exists($this->storage, $name)) {
            return call_user_func_array([$this->storage, $name], $arguments);
        }

        return null;
    }

    public function createDir(): bool
    {
        $path = dirname($this->path);
        if ($this->exists($path) === false) {
            return $this->makeDirectory($path);
        }
        return true;
    }
}
